x86-64: EFI MPS support
authorJan Beulich <jbeulich@novell.com>
Tue, 28 Jun 2011 08:21:28 +0000 (09:21 +0100)
committerJan Beulich <jbeulich@novell.com>
Tue, 28 Jun 2011 08:21:28 +0000 (09:21 +0100)
It's not clear this is needed - Linux doesn't use the MPS table even
if available, and no system having one was seen so far.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
xen/arch/x86/efi/boot.c
xen/arch/x86/efi/runtime.c
xen/arch/x86/mpparse.c
xen/include/xen/efi.h

index 9a959e306d9807d04442986c50d2152190229608..2e9d5532be23f0c340ca34449f956d4084d6f5a7 100644 (file)
@@ -897,12 +897,15 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     {
         static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID;
         static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID;
+        static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID;
         static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID;
 
         if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) )
               efi.acpi20 = (long)efi_ct[i].VendorTable;
         if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) )
               efi.acpi = (long)efi_ct[i].VendorTable;
+        if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) )
+              efi.mps = (long)efi_ct[i].VendorTable;
         if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) )
               efi.smbios = (long)efi_ct[i].VendorTable;
     }
index 6f4e4de77ba35e42feb73ed843a94621b72905fd..8274e22f3e1924db29d5288aa377090263a24a19 100644 (file)
@@ -29,6 +29,7 @@ void *__read_mostly efi_memmap;
 struct efi __read_mostly efi = {
        .acpi   = EFI_INVALID_TABLE_ADDR,
        .acpi20 = EFI_INVALID_TABLE_ADDR,
+       .mps    = EFI_INVALID_TABLE_ADDR,
        .smbios = EFI_INVALID_TABLE_ADDR,
 };
 
index 7dd6a7df7b671f7798ff0a068e8ff54e0cc5e7b1..e8720fd1f3c4924e376e3e277a3a915be88035fa 100644 (file)
@@ -19,6 +19,7 @@
 #include <xen/init.h>
 #include <xen/acpi.h>
 #include <xen/delay.h>
+#include <xen/efi.h>
 #include <xen/sched.h>
 
 #include <asm/bitops.h>
@@ -514,6 +515,14 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
        }
 }
 
+#define FIX_EFI_MPF FIX_KEXEC_BASE_0
+
+static __init void efi_unmap_mpf(void)
+{
+       if (efi_enabled)
+               __set_fixmap(FIX_EFI_MPF, 0, 0);
+}
+
 static struct intel_mp_floating *__initdata mpf_found;
 
 /*
@@ -528,6 +537,7 @@ void __init get_smp_config (void)
         * processors, where MPS only supports physical.
         */
        if (acpi_lapic && acpi_ioapic) {
+               efi_unmap_mpf();
                printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
                return;
        }
@@ -558,6 +568,7 @@ void __init get_smp_config (void)
                 * override the defaults.
                 */
                if (!smp_read_mpc((void *)(unsigned long)mpf->mpf_physptr)) {
+                       efi_unmap_mpf();
                        smp_found_config = 0;
                        printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
                        printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
@@ -584,6 +595,8 @@ void __init get_smp_config (void)
        } else
                BUG();
 
+       efi_unmap_mpf();
+
        printk(KERN_INFO "Processors: %d\n", num_processors);
        /*
         * Only use the first configuration found.
@@ -638,10 +651,37 @@ static int __init smp_scan_config (unsigned long base, unsigned long length)
        return 0;
 }
 
+static void __init efi_check_config(void)
+{
+       struct intel_mp_floating *mpf;
+
+       if (efi.mps == EFI_INVALID_TABLE_ADDR)
+               return;
+
+       __set_fixmap(FIX_EFI_MPF, PFN_DOWN(efi.mps), __PAGE_HYPERVISOR);
+       mpf = (void *)fix_to_virt(FIX_EFI_MPF) + ((long)efi.mps & (PAGE_SIZE-1));
+
+       if (memcmp(mpf->mpf_signature, "_MP_", 4) == 0 &&
+           mpf->mpf_length == 1 &&
+           mpf_checksum((void *)mpf, 16) &&
+           (mpf->mpf_specification == 1 || mpf->mpf_specification == 4)) {
+               smp_found_config = 1;
+               printk(KERN_INFO "SMP MP-table at %08"PRIx64"\n", efi.mps);
+               mpf_found = mpf;
+       }
+       else
+               efi_unmap_mpf();
+}
+
 void __init find_smp_config (void)
 {
        unsigned int address;
 
+       if (efi_enabled) {
+               efi_check_config();
+               return;
+       }
+
        /*
         * FIXME: Linux assumes you have 640K of base ram..
         * this continues the error...
index 390316439cd5199ba5f4a1709be6e50d9c4c5717..0e871a72be8857153e508104bda944686a255d83 100644 (file)
@@ -17,6 +17,7 @@ extern const bool_t efi_enabled;
 
 /* Add fields here only if they need to be referenced from non-EFI code. */
 struct efi {
+    unsigned long mps;          /* MPS table */
     unsigned long acpi;         /* ACPI table (IA64 ext 0.71) */
     unsigned long acpi20;       /* ACPI table (ACPI 2.0) */
     unsigned long smbios;       /* SM BIOS table */